From 26f7e5fa79ac33819b4c7207863a982fe09b2292 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 28 Mar 2007 15:02:54 +0000 Subject: [PATCH] [SVM] Inject a "fake" interrupt if we delay an interrupt for an exception (instead of just waiting for the next vmexit to inject the pending interrupt, since that could be some arbitrary number of instructions later). Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/intr.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index 89f3f30912..0730586308 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -67,20 +67,6 @@ asmlinkage void svm_intr_assist(void) int intr_type = APIC_DM_EXTINT; int intr_vector = -1; - /* - * Do not deliver a virtual interrupt (vintr) if an exception is pending. - * This is because the delivery of the exception can arbitrarily delay - * the injection of the vintr (for example, if the exception is handled - * via an interrupt gate, hence zeroing RFLAGS.IF). In the meantime the - * vTPR can be modified upwards and we can end up delivering the vintr - * when it is not in fact valid to do so (because we do not re-check the - * vTPR value). Moreover, the guest will be able to see the updated - * APIC/PIC state (as if the interrupt had been acknowledged) yet will not - * have actually received the interrupt. This could confuse the guest! - */ - if ( vmcb->eventinj.fields.v ) - return; - /* * Previous Interrupt delivery caused this intercept? * This will happen if the injection is latched by the processor (hence @@ -115,11 +101,23 @@ asmlinkage void svm_intr_assist(void) return; /* - * Create a 'fake' virtual interrupt on to intercept as soon as the - * guest _can_ take interrupts. Do not obtain the next interrupt from - * the vlapic/pic if unable to inject. + * If the guest can't take an interrupt right now, create a 'fake' + * virtual interrupt on to intercept as soon as the guest _can_ take + * interrupts. Do not obtain the next interrupt from the vlapic/pic + * if unable to inject. + * + * Also do this if there is an exception pending. This is because + * the delivery of the exception can arbitrarily delay the injection + * of the vintr (for example, if the exception is handled via an + * interrupt gate, hence zeroing RFLAGS.IF). In the meantime: + * - the vTPR could be modified upwards, so we need to wait until the + * exception is delivered before we can safely decide that an + * interrupt is deliverable; and + * - the guest might look at the APIC/PIC state, so we ought not to have + * cleared the interrupt out of the IRR. */ - if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow ) + if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow + || vmcb->eventinj.fields.v ) { vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1); -- 2.30.2